﻿using OneSpider.API;
using OneSpider.Comparer;
using OneSpider.Models.ResultModel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OneSpider.Extensions;
using OneSpider.DbContexts;
using One.Models;

namespace OneSpider.Helper
{
    public class Spider
    {
        #region Start date
        private readonly DateTime ContentStartDate = new DateTime(2012, 10, 1);

        private readonly DateTime EssayStartDate = new DateTime(2012, 1, 1);

        private readonly DateTime MusicStartDate = new DateTime(2013, 1, 1);

        private readonly DateTime SerialStartDate = new DateTime(2016, 1, 1);

        private readonly DateTime AnswerStartDate = new DateTime(2012, 10, 1);
        #endregion

        #region fields
        private List<string> contentVolList = new List<string>();
        private List<string> userNameList = new List<string>();
        private List<int> essayIdList = new List<int>();
        private List<int> answerIdList = new List<int>();
        private List<int> serialIdList = new List<int>();
        private List<int> musicIdList = new List<int>();
         
        List<Article> articles = new List<Article>();
        List<Content> contents = new List<Content>();
        List<Author> authors = new List<Author>();
        List<Answer> answers = new List<Answer>();
        List<Serial> serials = new List<Serial>();
        List<Tag> tags = new List<Tag>();

        OneDataContext dataContext = new OneDataContext();
        
        #endregion

        /// <summary>
        /// 爬取首页内容
        /// </summary>
        public async Task GetMainPageContent()
        {
            DateTime startTime = DateTime.Now;
            while (startTime > ContentStartDate)
            {
                var response = await ApiService.GetMainPageAsync(startTime.Date.ToString("yyyy-MM-dd"));
                if (response != null && response.Count != 0)
                {
                    foreach (var item in response)
                    {
                        if (!contentVolList.Contains(item.HpTitle))
                        {
                            contentVolList.Add(item.HpTitle);

                            LogHelper.WriteLine($"GetMainPage {startTime.Date.ToString("yyyy-MM-dd")} : {item.ContentId} {item.HpTitle}");
                            contents.Add(item.ToContent());
                        }
                    } 

                    startTime = startTime.Subtract(new TimeSpan(response.Count, 0, 0, 0));
                }
                else
                {
                    break;
                }
            }
             
            LogHelper.WriteLine($"GetMainPage Totals : {contents.Count}");
        }
         
        /// <summary>
        /// 爬取文章
        /// </summary>
        public async Task GetArticle()
        {
            DateTime startTime = EssayStartDate;
            while (startTime <= DateTime.Now)
            {
                var response = await ApiService.GetEssayAsync(startTime.Date.ToString("yyyy-MM-dd"));
                if (response == null || response.Count == 0)
                {
                    startTime = startTime.AddDays(2);
                }
                else
                {
                    foreach (var essay in response)
                    {
                        if (!essayIdList.Contains(essay.ContentId))
                        {
                            essayIdList.Add(essay.ContentId);
                            ArticleDetailResult essayDetailResult = await ApiService.GetEssayDetailAsync(essay.ContentId);
                            Article tmp = essayDetailResult.ToArticle();
                             
                            Author author = essay.Author[0].ToAuthor();
                            tmp.Author = GetAuthorInDB(author); 
                            articles.Add(tmp); 
                            LogHelper.WriteLine($"GetEssay {startTime.Date.ToString("yyyy-MM-dd")} : {essay.HpTitle} {essay.ContentId}");
                        }

                        startTime = startTime.AddDays(response.Count);
                    } 
                }
            }

            dataContext.Articles.AddRange(articles);
            dataContext.SaveChanges();

            LogHelper.WriteLine($"GetEssay Totals : {articles.Count}");
        }
        
        
        /// <summary>
        /// 获取音乐
        /// </summary>
        //public async Task GetMusic()
        //{
        //    DateTime startTime = MusicStartDate;
        //    while (startTime <= DateTime.Now)
        //    {
        //        var response = await ApiService.GetMusicAsync(startTime.Date.ToString("yyyy-MM-dd"));
        //        if (response != null && response.Count != 0)
        //        {
        //            response.ForEach(x =>
        //            {
        //                if (!musicIdList.Contains(x.Id))
        //                {
        //                    if (x.Author != null)
        //                    {
        //                        if (!userNameList.Contains(x.Author.UserName))
        //                        {
        //                            DatabaseHelper<User>.Insert(x.Author);
        //                            userNameList.Add(x.Author.UserName);
        //                        }

        //                        foreach (var item in x.AuthorList)
        //                        {
        //                            if (!userNameList.Contains(item.UserName))
        //                            {
        //                                DatabaseHelper<User>.Insert(x.Author);
        //                                userNameList.Add(item.UserName);
        //                            }
        //                        }
        //                    }

        //                    musicIdList.Add(x.Id);
        //                    DatabaseHelper<Music>.Insert(response);
        //                    LogHelper.WriteLine($"GetMusic {startTime.Date.ToString("yyyy-MM-dd")} : {x.Id} {x.Title}");
        //                }
        //            });
        //        }

        //        startTime = startTime.AddDays(response.Count);
        //    }
        //}

        /// <summary>
        /// 获取连载
        /// </summary>
        public async Task GetSerial()
        {
            DateTime startTime = SerialStartDate;
            while (startTime <= DateTime.Now)
            {
                var response = await ApiService.GetSerialAsync(startTime.Date.ToString("yyyy-MM-dd"));
                if (response != null && response.Count != 0)
                {
                    response.ForEach(serialResult =>
                    {
                        if (!serialIdList.Contains(serialResult.Id))
                        {
                            serialIdList.Add(serialResult.Id);
                            Author author = serialResult.AuthorList[0].ToAuthor();

                            LogHelper.WriteLine(serialResult.Author.UserName);

                            Serial serial = serialResult.ToSerial();
                            serial.Author = GetAuthorInDB(author);
                            serials.Add(serial);
                            LogHelper.WriteLine($"GetSerial {startTime.Date.ToString("yyyy-MM-dd")} : {serial.Id} {serial.Title}");
                        }
                    });
                }

                startTime = startTime.AddDays(response.Count);
            }

            dataContext.Serials.AddRange(serials);
            dataContext.SaveChanges();
            LogHelper.WriteLine($"GetSerial Total : {serials.Count}");
        }
        

        /// <summary>
        /// 获取问答
        /// </summary>
        public async Task GetAnswer()
        {
            DateTime tmp = AnswerStartDate;
            while (tmp <= DateTime.Now)
            {
                var response = await ApiService.GetAnswerAsync(tmp.Date.ToString("yyyy-MM-dd"));

                foreach (var qa in response)
                {
                    if (!answerIdList.Contains(qa.Id))
                    {
                        answerIdList.Add(qa.Id);
                        Answer answer = qa.ToAnswer();

                        AnswerDetailResult answerDetailResult = await ApiService.GetAnswerDetailAsync(qa.Id);

                        answer.AnswerContent = answerDetailResult.AnswerContent;
                        answer.ChargeEditor = answerDetailResult.ChargeEditor;
                        answer.QuestionContent = answerDetailResult.QuestionContent;

                        answers.Add(answer);

                        LogHelper.WriteLine($"GetAnswer {tmp.Date.ToString("yyyy-MM-dd")} : {qa.Id} {qa.QuestionTitle}");
                    }
                }
                
                tmp = tmp.AddDays(response.Count);
            } 
            LogHelper.WriteLine($"GetAnswer Totals : {answers.Count}");
        }

        public Author GetAuthorInDB(Author author)
        {
            if (author == null)
            {
                return null;
            }

            if (dataContext.Authors.Any(x => x.Name.Equals(author.Name)))
            {
                return dataContext.Authors.FirstOrDefault(x => x.Name.Equals(author.Name));
            }
            else
            {
                dataContext.Authors.Add(author);
                dataContext.SaveChanges(); 
                return dataContext.Authors.FirstOrDefault(x => x.Name.Equals(author.Name));
            }
        }


        public async Task RunAsync()
        {
            await GetMainPageContent();
            //await GetArticle();
            await GetSerial();
            //await GetMusic();
            await GetAnswer();

            //DatabaseHelper<Tag>.Insert(tags);
            //DatabaseHelper<Author>.Insert(authors);

            DatabaseHelper<Content>.Insert(contents);
            DatabaseHelper<Answer>.Insert(answers);
            //DatabaseHelper<Serial>.Insert(serials);
        }
    }
}
